
#ifndef _244_FINAL_PROJECT_UTIL_H_
#define _244_FINAL_PROJECT_UTIL_H_

#include <exception>


#define ODBC_FAILED(rv) ((rv) != SQL_SUCCESS && (rv) != SQL_SUCCESS_WITH_INFO)


//might not be needed any longer
template <class K>
class SingleLoad {
private:
    static bool loaded = false;
public:
    static void load() { loaded = true; }
    static void unload() { loaded = false; }
    static bool isLoaded() { return loaded; }
};

class Uncopyable {
private:
    Uncopyable(const Uncopyable &o) {}
    Uncopyable& operator = (const Uncopyable &o) {}
};


//might not be needed any longer
class DataManagementException : public std::exception {
public:
    SqlException() : std::exception("DataManagementException") {}
	SqlException(std::string reason) : std::exception(("DataManagementException: " + reason).c_str()) {}
};

class SqlException : public std::exception {
public:
	SqlException() : std::exception("SqlException") {}
	SqlException(std::string reason) : std::exception(("SqlException: " + reason).c_str()) {}
};


class RaiiSQLAllocHandle {
private:
	SQLRETURN rv;
	SQLSMALLINT handle_type;
	SQLHANDLE handle;
	bool freed;
	//int id;
	static int counter;
public:
	RaiiSQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle) : 
			handle_type(HandleType), freed(false) {
		rv = SQLAllocHandle(HandleType, InputHandle, OutputHandle);
		if(ODBC_FAILED(rv))
			freed = true;

		//id = ++counter;

		handle = *OutputHandle;
	}
	~RaiiSQLAllocHandle() {
		free();
	}

	SQLRETURN result() { return rv; }
	SQLRETURN free() {
		//std::cerr << "free: " << id;
		if(!freed) {
			//std::cerr << " doing free";
			rv = SQLFreeHandle(handle_type, handle);
		}
		//std::cerr << std::endl;

		freed = true;

		return rv;
	}
};


#endif // inclusion guard

